/**
 * 
 */
package io.dora.remoting;

import io.dora.rpc.RpcInvocation;
import io.dora.rpc.RpcRequest;
import io.dora.rpc.RpcResponse;
import io.dora.utils.ReflectionUtils;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 服务提供方请求处理器
 * 
 * @author zhaohongbo
 *
 */
public class ProviderHandler extends ChannelHandlerAdapter {
	
	private Logger logger = LoggerFactory.getLogger(ProviderHandler.class);
	
	protected Map<String, Object> serviceMap;
	
	public ProviderHandler() {
		
	}
	
	public ProviderHandler(Map<String, Object> serviceMap) {
		this.serviceMap = serviceMap;
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		ctx.close();
		super.exceptionCaught(ctx, cause);
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		
		logger.info("ProviderHandler channel read");
		if (msg == null || !msg.getClass().equals(RpcRequest.class)) {
			return;
		}
		
		RpcRequest request = (RpcRequest) msg;
		RpcInvocation invocation = (RpcInvocation) request.getData();
		Object target = serviceMap.get(invocation.getServiceKey());
		Object resultObject = ReflectionUtils.invokeMethod(target, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getParameters());
		RpcResponse response = new RpcResponse(request.getId());
		response.setData(resultObject);
		ctx.write(response);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
		super.channelReadComplete(ctx);
	}
	
}
